package org.nanhill.xmlro.sro.spring;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.nanhill.commons.lang.ReflectCache;
import org.nanhill.xmlro.sro.SroHelper;

public class SroMultiControllerExporter extends SroAbstractControllerExporter {

	/**
	 * Service expose name and service instance name(used by spring) mapping
	 */
	private Map<String, Object> serviceMap = new HashMap<String, Object>();

	public void setServiceMap(Map<String, Object> serviceMap) {
		this.serviceMap = serviceMap;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.nanhill.xmlro.spring.AbstractXmlroControllerExporter#getCallServiceInstance(javax.servlet.http.HttpServletRequest)
	 */
	@Override
	protected Object getCallService(HttpServletRequest request)
			throws Exception {
		// get service name called by client
		String serviceExposeName = request.getParameter(SroHelper.SRO_SERVICE);
		if (null == serviceExposeName) {
			throw new ServletException(
					"Http request must contains a parameter ["
							+ SroHelper.SRO_SERVICE
							+ "] to call Sro Multi Exporter's service!");
		}
		if (!serviceMap.containsKey(serviceExposeName)) {
			throw new Exception("Sro remote call service exposeName: "
					+ serviceExposeName + " not exist!");
		}
		Object serviceInstance = this.serviceMap.get(serviceExposeName);
		return serviceInstance;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.nanhill.xmlro.spring.AbstractXmlroControllerExporter#getCallMethod(javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected Method getCallMethod(HttpServletRequest request, Object service)
			throws Exception {
		// get method name
		String methodName = request.getParameter(SroHelper.SRO_METHOD);
		if (null == methodName) {
			throw new ServletException(
					"Http request must contains a parameter ["
							+ SroHelper.SRO_METHOD
							+ "] to call Sro Multi Exporter's method!");
		}
		// {{get RPC method
		Class serviceClass = service.getClass();
		// invoke the first public method by the input method name
		Method method = ReflectCache.getFirstPublicMethod(serviceClass,
				methodName);
		// }}
		return method;
	}

}
